package org.luxor.storage.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.codec.digest.Md5Crypt;
import org.luxor.commons.core.exception.BaseException;
import org.luxor.commons.core.utils.BeanUtils;
import org.luxor.commons.core.utils.HttpContextUtils;
import org.luxor.commons.core.utils.StrKit;
import org.luxor.commons.jdbc.annotation.DS;
import org.luxor.commons.storage.constant.StorageType;
import org.luxor.commons.storage.exception.StorageServiceException;
import org.luxor.commons.storage.service.IFileStorageService;
import org.luxor.storage.entity.OssFileEntity;
import org.luxor.storage.mapper.OssFileMapper;
import org.luxor.storage.service.IOssFileMgrService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.Map;

/**
 * OSS文件服务
 *
 * @author Mr.yan @date 2020/3/14
 */
@Service
@DS("${spring.storage.dataSource:master}")
public class OssFileMgrServiceImpl extends ServiceImpl<OssFileMapper, OssFileEntity> implements IOssFileMgrService {

    @Autowired
    private IFileStorageService fileStorageService;

    @Override
    public IPage<OssFileEntity> page(IPage<OssFileEntity> page, Map search) {
        OssFileEntity query = BeanUtils.toObject(OssFileEntity.class, search);
        return super.page(page, Wrappers.query(query));
    }

    @Override
    public OssFileEntity upload(StorageType storageType, MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        String fileSuffix = fileName.substring(fileName.lastIndexOf(StrKit.DOT) + 1);
        String md5 = Md5Crypt.md5Crypt(file.getBytes());
        // 保存
        String fileFullPath = fileStorageService.upload(storageType, file.getBytes(), fileName, fileSuffix);
        String fileUrl = fileStorageService.getFileUrl(storageType, fileFullPath);

        OssFileEntity ossFile = getByMd5(md5);
        if (ossFile == null || ossFile.getId() == null) {
            ossFile = new OssFileEntity();
            ossFile.setRemarkName(file.getOriginalFilename());
            ossFile.setContentType(file.getContentType());
            ossFile.setFilePostfix(file.getOriginalFilename());
            ossFile.setFileSize(file.getSize());
            ossFile.setMd5(md5);
            ossFile.setStorageType(storageType.getCode());
            ossFile.setUrl(fileUrl);
            ossFile.setFileFullPath(fileFullPath);
            ossFile.setUpdateTime(new Date());
            this.save(ossFile);
        }
        return ossFile;
    }

    @Override
    public void download(StorageType storageType, String fileFullPath, HttpServletResponse response) {
        try {
            byte[] fileByte = fileStorageService.download(storageType, fileFullPath);
            HttpContextUtils.write(fileByte, response);
        } catch (BaseException e) {
            throw new StorageServiceException("HttpServletResponse Write Fault!");
        }
    }

    private OssFileEntity getByMd5(String md5) {
        Wrapper<OssFileEntity> wrapperQuery = Wrappers.<OssFileEntity>lambdaUpdate()
                .eq(OssFileEntity::getMd5, md5);
        return getOne(wrapperQuery, false);
    }

    @Override
    public boolean checkMd5(String md5) {
        Wrapper<OssFileEntity> wrapperQuery = Wrappers.<OssFileEntity>lambdaUpdate()
                .eq(OssFileEntity::getMd5, md5);
        return this.getOne(wrapperQuery, false) == null;
    }


}
